

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from PyKDE4.plasma import Plasma

from PyKDE4.kdeui import KIcon
from PyKDE4.kdeui import KIconLoader
from PyKDE4.kdeui import KWindowSystem
from PyKDE4.kdeui import KApplication

class OSDWidget(QGraphicsView):
    def __init__(self, parent=None):
        QGraphicsView.__init__(self, parent)
        
        self.setWindowFlags(Qt.X11BypassWindowManagerHint)
        self.setFrameStyle(QFrame.NoFrame)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.viewport().setAutoFillBackground(False)
        self.setAttribute(Qt.WA_TranslucentBackground)
        
        if Plasma.Theme.defaultTheme().imagePath("icons/audio"):
            # Icons from plasma theme are 24x24 pixel (W,H)
            iconSize = (24, 24)
            svgIcon = Plasma.Svg(self)
            svgIcon.setImagePath("icons/audio")
            svgIcon.setContainsMultipleImages(True)
            svgIcon.resize(*iconSize)
            self._volumeHighPixmap = svgIcon.pixmap("audio-volume-high")
            self._volumeMediumPixmap = svgIcon.pixmap("audio-volume-medium")
            self._volumeLowPixmap = svgIcon.pixmap("audio-volume-low")
            self._volumeMutedPixmap = svgIcon.pixmap("audio-volume-muted")
        else:
            iconSize = (KIconLoader.SizeSmallMedium, KIconLoader.SizeSmallMedium)
            self._volumeHighPixmap = KIcon("audio-volume-high").pixmap(iconSize)
            self._volumeMediumPixmap = KIcon("audio-volume-medium").pixmap(iconSize)
            self._volumeLowPixmap = KIcon("audio-volume-low").pixmap(iconSize)
            self._volumeMutedPixmap = KIcon("audio-volume-muted").pixmap(iconSize)
        
        self._background = Plasma.FrameSvg(self)
        self._background.setImagePath("widgets/tooltip")
        
        self._iconLabel = Plasma.Label()
        self._iconLabel.nativeWidget().setPixmap(self._volumeHighPixmap)
        self._iconLabel.nativeWidget().setFixedSize(*iconSize)
        self._iconLabel.setMinimumSize(*iconSize)
        self._iconLabel.setMaximumSize(*iconSize)
        
        self._meter = Plasma.Meter()
        self._meter.setMeterType(Plasma.Meter.BarMeterHorizontal)
        self._meter.setMaximum(100)
        self._meter.setMaximumHeight(iconSize[1])
        
        self._volumeLabel = Plasma.Label()
        self._volumeLabel.setAlignment(Qt.AlignCenter)
        self._volumeLabel.setMinimumHeight(iconSize[1])
        self._volumeLabel.setMaximumHeight(iconSize[1])
        self._volumeLabel.nativeWidget().setFixedHeight(iconSize[1])
        self._volumeLabel.setWordWrap(False)
        
        # Set a fixed width for the volume label. To do that we need the text with the maximum width
        # (this is true if the volume is at 100%). We simply achieve that by calling "setCurrentVolume".
        self.setCurrentVolume(100, False)
        self.themeUpdated()
        
        # Setup the auto-hide timer
        self._hideTimer = QTimer(self)
        self._hideTimer.setInterval(2000)
        self._hideTimer.setSingleShot(True)
        self._hideTimer.timeout.connect(self.hide)
        
        # Setup the OSD layout
        self._container = QGraphicsWidget()
        layout = QGraphicsLinearLayout(self._container)
        layout.addItem(self._iconLabel)
        layout.addItem(self._meter)
        layout.addItem(self._volumeLabel)
        
        self._scene = QGraphicsScene(self)
        self._scene.addItem(self._container)
        
        Plasma.Theme.defaultTheme().themeChanged.connect(self.themeUpdated) # e.g. for updating font
        
        self.setScene(self._scene)
        
    def activateOSD(self):
        """Only starts hide timer"""
        self._hideTimer.start()
    
    def themeUpdated(self):
        # Set a font which makes the text appear as big (height-wise) as the meter.
        # QFont font = QFont(self._volumeLabel.nativeWidget().font())
        theme = Plasma.Theme.defaultTheme()
        
        
        palette = self._volumeLabel.palette()
        palette.setColor(QPalette.WindowText, theme.color(Plasma.Theme.TextColor))
        self._volumeLabel.setPalette(palette)
        
        font = theme.font(Plasma.Theme.DefaultFont)
        font.setPointSize(15)
        self._volumeLabel.setFont(font)
        qfm = QFontMetrics(font)
        textSize = qfm.boundingRect("100 %  ")
        
        widthHint = textSize.width()
        #heightHint = textSize.height()
        #self.setCurrentVolume(100,false)
        self._volumeLabel.setMinimumWidth(widthHint)
        self._volumeLabel.setMaximumWidth(widthHint)
        self._volumeLabel.nativeWidget().setFixedWidth(widthHint)
        
    def setCurrentVolume(self, volumeLevel, muted=False):
        """Set volume level in percent"""
        self._meter.setValue(volumeLevel)
        
        if not muted and (volumeLevel > 0):
            if volumeLevel < 30:
                self._iconLabel.nativeWidget().setPixmap(self._volumeLowPixmap)
            elif volumeLevel < 70:
                self._iconLabel.nativeWidget().setPixmap(self._volumeMediumPixmap)
            else:
                self._iconLabel.nativeWidget().setPixmap(self._volumeHighPixmap)
        else:
            self._iconLabel.nativeWidget().setPixmap(self._volumeMutedPixmap)
        
        # Show the volume %
        self._volumeLabel.setText("%d %%" % volumeLevel) # if you change the text, please adjust textSize in themeUpdated()
        
    def drawBackground(self, painter, rectF):
        painter.save()
        painter.setCompositionMode(QPainter.CompositionMode_Source)
        self._background.paintFrame(painter)
        painter.restore()

    def sizeHint(self):
        iconSize = self._iconLabel.nativeWidget().pixmap().height()
        labelWidth = self._volumeLabel.nativeWidget().size().width()
        meterHeight = iconSize
        meterWidth = iconSize * 12
        left, top, right, bottom = self._background.getMargins()
        return QSize(meterWidth + labelWidth + iconSize + left + right, meterHeight + top + bottom)

    def resizeEvent(self, event):
        self._background.resizeFrame(QSizeF(self.size()))
        self._container.setGeometry(0, 0, self.width(), self.height())
        left, top, right, bottom = self._background.getMargins()
        self._container.layout().setContentsMargins(left, top, right, bottom)
        
        self._scene.setSceneRect(0, 0, self.width(), self.height())
        if not KWindowSystem.compositingActive():
            self.setMask(self._background.mask())

    def showEvent(self, event):
        Plasma.WindowEffects.overrideShadow(self.winId(), True)
        Plasma.WindowEffects.enableBlurBehind(self.winId(), True, self._background.mask())


if __name__=='__main__':
    app = QApplication([])
    
    osd = OSDWidget()
    osd.setCurrentVolume(82)
    osd.show()
    #osd.activateOSD()
    
    rect = app.desktop().screenGeometry(QCursor.pos())
    size = osd.sizeHint()
    posX = rect.x() + (rect.width() - size.width()) / 2
    posY = rect.y() + 4 * rect.height() / 5
    osd.setGeometry(posX, posY, size.width(), size.height())
    
    app.exec_()
    